//
//  SocketUtil.swift
//  pluto
//
//  Created by andyge on 15/7/28.
//  Copyright © 2015年 gejingguo. All rights reserved.
//

import Foundation
//import Dispatch

func sockaddr_cast(p: UnsafeMutablePointer<sockaddr_in>) -> UnsafeMutablePointer<sockaddr> {
    return UnsafeMutablePointer<sockaddr>(p)
}

func socklen_t_cast(p: UnsafeMutablePointer<socklen_t>) -> UnsafeMutablePointer<socklen_t> {
    return UnsafeMutablePointer<socklen_t>(p)
}

func ntohs(value: CUnsignedShort) -> CUnsignedShort {
    // hm, htons is not a func in OSX and the macro is not mapped
    return (value << 8) + (value >> 8);
}
let htons = ntohs // same thing, swap bytes :-)


func setSocketOption(fd: Int32, option: Int32, value: Int32) -> Error? {
    
    var buf = value
    let rc  = setsockopt(fd, SOL_SOCKET, option, &buf,socklen_t(sizeof(Int32)))
    
    if rc != 0 { // ps: Great Error Handling
        //println("Could not set option \(option) on socket \(self)")
        return TcpError(err: TcpErrorNo.TcpErrorNo_SocketSetOption.rawValue)
    }
    
    return nil
}

func getSocketOption(fd: Int32, option: Int32) -> (Error?, Int32?) {
    
    var buf    = Int32(0)
    var buflen = socklen_t(sizeof(Int32))
    
    let rc = getsockopt(fd, SOL_SOCKET, option, &buf, &buflen)
    if rc != 0 { // ps: Great Error Handling
        //println("Could not get option \(option) from socket \(self)")
        return (TcpError(err: TcpErrorNo.TcpErrorNo_SocketGetOption.rawValue), nil)
    }
    
    return (nil, buf)
}

func getSocketFlags(fd: Int32) -> (err: Error?, flags: Int32?) {
    let rc = c_getFileFlags(fd)
    if rc < 0 {
        return (TcpError(err: TcpErrorNo.TcpErrorNo_SocketGetOption.rawValue), nil)
    }
    
    return (nil, rc)
}

func setSocketFlags(fd: Int32, flags: Int32) -> Error? {
    let rc = c_setFileFlags(fd, flags)
    if rc < 0 {
        return TcpError(err: TcpErrorNo.TcpErrorNo_SocketSetOption.rawValue)
    }
    
    return nil
}

func setSocketNonBlocking(fd: Int32) -> Error? {
    let rc = getSocketFlags(fd)
    if rc.err != nil {
        return rc.err
    }
    
    return setSocketFlags(fd, flags: rc.flags! | O_NONBLOCK)
}

func setSocketReuseAddr(fd: Int32) -> Error? {
    
    return setSocketOption(fd, option: SO_REUSEADDR, value: 1)
}

public func testFunc() {
    print("hello test func.")
}


